<html>
    <head>
        <title>behavior:virtual-list</title>
        <style>

tape {
  behavior: virtual-list;
  prototype: Tape;
  display:block;
  flow:vertical;
  overflow:scroll-indicator;
  size:*;
  border:1px solid;
  vertical-align: bottom; // last "messages" are seen first
}

tape > div {
  height:6em;
  border:1px solid blue;
}

        </style>
        <script>

class Tape extends Element {
    nItems = 2000;

    // scroll down
    appendElements(index, n) {
        if (index === undefined) index = 0;
        const elements = [];
        for (let i = 0; i < n; ++i, ++index) {
            if (index >= this.nItems) break;
            elements.push(this.renderItem(index));
        }

        this.append(elements);
        return {moreafter: (this.nItems - index)}; // return estimated number of items below this chunk
    }

    // scroll up
    prependElements(index, n) {
        if (index === undefined) index = this.nItems - 1;
        const elements = [];
        for (let i = 0; i < n; ++i, --index) {
            if (index < 0) break;
            elements.push(this.renderItem(index));
        }

        elements.reverse();
        this.prepend(elements);
        return {morebefore: (index < 0 ? 0 : index + 1)}; // return estimated number of items above this chunk
    }

    // scroll to
    replaceElements(index, n) {
        const elements = [];
        const start = index;
        for (let i = 0; i < n; ++i, ++index) {
            if (index >= this.nItems) break;
            elements.push(this.renderItem(index));
        }

        this.patch(elements);
        return {
            morebefore: (start <= 0 ? 0 : start),
            moreafter: (this.nItems - index),
        }; // return estimated number of items before and above this chunk
    }

    renderItem(index) {
        return <div key={index}>item { index }</div>;
    }

    oncontentrequired(evt) {
        const {length, start, where} = evt.data;

        if (where > 0)
        // scrolling down, need to append more elements
            evt.data = this.appendElements(start, length);
        else if (where < 0)
        // scrolling up, need to prepend more elements
            evt.data = this.prependElements(start, length);
        else
        // scrolling to index
            evt.data = this.replaceElements(start, length);

        return true;
    }

    /*
  onanimationstart(evt) {
    console.log("animated scroll start");
  }
  onanimationend(evt) {
    console.log("animated scroll end");
  }*/

    /*onscroll() {
    console.log("scroll");
  }*/
}

        </script>
    </head>
    <body>

<tape/>

    </body>
</html>